1. 操作系统概论
本节中可能会引入大量全新的概念,但请不要慌张——这些概念都会在后续章节中进行详细的阐述。现在只需要形成一个模糊的但能够纵览整个课程内容的认知就好。
本节内容需要随时在某个概念被详细介绍后添加指向对应介绍笔记的链接。
程序运行时会发生什么?很简单:执行指令。处理器从内存中取出一条指令,对其解码(确定指令的行为),然后执行。完成一条指令后,执行下一条指令。
有一类程序负责让程序运行变得容易,这就是 操作系统(Operation System,OS)。操作系统允许多个程序同时执行,允许程序共享内存,允许程序与设备交互等等。要做到这一点,操作系统主要利用一种叫做 虚拟化(Virtualization) 的技术,即将物理资源(如处理器、内存与磁盘)转换为更通用、更强大且易于使用的虚拟形式。因此,操作系统也被称作 虚拟机(Virtual Machine)。而这也引出了本课程将要阐述的关键问题:
本课程依照不同的主题分章节,每一个章节都会首先以上面所示的方框标注出关键问题,并在剩下的篇幅中详细介绍问题的解决方案。
带着这些关键问题阅读笔记将对于理解并掌握其中的内容有很大的帮助。
为了让程序与用户能够利用操作系统的功能,操作系统自身必须对外提供一些服务或 API 供程序调用,这些接口被统称为 系统调用(System Call)。通过这些接口,应用程序就可以完成诸如访问内存与设备等操作。因此我们也称操作系统为应用程序提供了一个 标准库。
操作系统负责管理所有虚拟化的物理资源供应用程序使用,并尽量做到高效与公平。从这个角度来说操作系统也可被称为 资源管理器。
本课程将讲解三个与操作系统相关的主题:虚拟化、并发与持久性,下面是对这三个主题的简要概述:
虚拟化
操作系统允许多个程序同时运行,即使机器只拥有单个或少量 CPU 核心。这是因为操作系统将 CPU 虚拟化,提供一种假象:系统拥有非常多的 CPU 核心,每个程序都可以独立在某个核心上运行。然而事实是,操作系统依据其调度程序的策略,定期停止某些程序的运行,并将 CPU 的控制权交给其它程序,调度的周期非常短暂,以至于产生了多个程序同时运行的假象。操作系统有一些接口与程序负责处理程序的运行与终止,第 2 ~ 5 节将详细讨论背后的原理:
- 2. 进程与进程 API 讲述操作系统为在 CPU 上运行的程序提供的抽象:进程,以及相关的操作 API。
- 3. 受限直接执行 讲述操作系统实现进程抽象与提供多个程序同时运行在 CPU 上这一假象的底层机制。
- 4. 进程调度策略 讲述操作系统安排进程在 CPU 上运行顺序的策略。
- 5. 多处理器调度 为进阶内容,需要 并发 部分的知识为基础,讲述在现代的多核处理器上调度程序的策略。
程序运行需要内存。程序将所有数据结构保存在内存中,程序运行时需要频繁访问内存。内存就是一个字节数组,每个字节都有一个对应的地址,从内存中存取数据都需要给出对应的地址。操作系统虚拟化内存,为每个进程都提供一个私有的虚拟地址空间(Virtual Address Space),提供给程序完全拥有自己的物理内存的假象。所有进程的虚拟地址空间互不干扰。然而事实是,操作系统将物理内存视作共享资源管理并分配给各个程序,并通过某种方式将虚拟内存映射到机器的物理内存上。第 6 ~ 11 节将详细讨论背后的机制。
并发
并发(Concurrency) 用于指代一类问题,这类问题出现于需要同时处理很多任务时,涉及指令执行顺序、资源管理等。并发会带来大量奇怪且难以解决的问题。因此,构建正确的并发程序就显得尤为重要。第(待补充)节将详细讨论这个话题。
持久性
现代计算机的物理内存采用的多为 DRAM 芯片,其掉电数据就会丢失。因此,我们需要硬件与软件来持久的保持数据,这便是 持久性(Persistence) 相关的话题。
硬件以某种输入/输出(Input/Output,I/O)设备的形式出现。当前常见的持久存储数据的硬件便是硬盘驱动器(俗称机械硬盘)与固态硬盘(SSD)。操作系统中负责管理磁盘的软件被称作 文件系统(File System),其负责以可靠且高效的方式将用户创建的任何文件存储在硬盘上。
与操作系统对 CPU 与内存提供的抽象不同,操作系统不会为每个程序提供独占的硬盘空间,而是允许程序共享不同文件中的信息。
为了完成数据真正被写入硬盘中,以及保证这一过程的高效与可靠性,操作系统需要做很多事情,这些都将在第(待补充)节详细讨论。
设计目标
总结一下操作系统的功能:
- 取得CPU、内存与硬盘等物理资源并将之虚拟化。
- 处理并发问题
- 在硬盘上持久地保持文件,确保数据安全不会丢失。
这些功能归根结底都是为了实现一个目标:通过提供一些 抽象,使得系统更加方便且易于使用,无需关注内部复杂而无聊的细节。
此外,设计操作系统还有如下目标:
- 需要具备 高性能,即 最小化操作系统的开销。
- 需要在应用程序之间和操作系统与应用程序之间提供 保护,确保某些程序恶意或偶然的不良行为不会伤害到其它程序。保护的关键是 隔离。
- 力求提供高度的可靠性。由于其它应用程序依赖操作系统运行,操作系统必须不间断运行。一旦操作系统失效,其上的所有应用程序也会失效。
发展历史
简单概括一下:
- 起初就是 批处理程序+一组常用函数库。
- 随后引入了 系统调用 的概念,用户态与内核态分离。
- 多道程序时代,引入了分时操作与进程隔离的概念。内存保护与并发相关的问题也逐渐浮现。
在这一过程中,Unix起到了举足轻重的作用,并随之诞生了许多智慧的思想。其中最著名的当属 KISS 原则:Keep it simple, stupid.。其含义为:将复杂任务拆分为多个简单的任务,为每一个简单的任务构建小而强大的程序,将所有只专精某一个任务的程序串联起来以形成更大的解决问题的工作流。